using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Terra.Data.Entities.Identity;
using Terra.Data.Repository;
using Terra.Data.Context;
namespace Terra.Data.Repository.Identity
{
    /// <summary>
    /// 权限仓储实现
    /// </summary>
    public class PermissionRepository : RepositoryBase<Permission, Guid>, IPermissionRepository
    {
        private readonly TerraDbContext _terraDbContext;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="context">数据库上下文</param>
        public PermissionRepository(TerraDbContext context) : base(context)
        {
            _terraDbContext = context;
        }

        /// <summary>
        /// 获取用户权限码列表
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <returns>权限码列表</returns>
        public async Task<List<string>> GetUserPermissionCodesAsync(Guid userId)
        {
            // 获取用户角色
            var roleIds = await _terraDbContext.UserRoles
                .Where(ur => ur.UserId == userId)
                .Select(ur => ur.RoleId)
                .ToListAsync();

            // 获取角色权限
            var permissionCodes = await _terraDbContext.Set<RolePermission>()
                .Where(rp => roleIds.Contains(rp.RoleId))
                .Join(_terraDbContext.Set<Permission>(),
                    rp => rp.PermissionId,
                    p => p.Id,
                    (rp, p) => p.Code)
                .Where(code => code != null)
                .Distinct()
                .ToListAsync();

            return permissionCodes;
        }

        /// <summary>
        /// 获取用户菜单权限列表
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <returns>菜单列表</returns>
        public async Task<List<Menu>> GetUserMenusAsync(Guid userId)
        {
            // 获取用户角色
            var roleIds = await _terraDbContext.UserRoles
                .Where(ur => ur.UserId == userId)
                .Select(ur => ur.RoleId)
                .ToListAsync();

            // 获取角色权限关联的菜单
            var menus = await _terraDbContext.Set<RolePermission>()
                .Where(rp => roleIds.Contains(rp.RoleId))
                .Join(_terraDbContext.Set<Permission>(),
                    rp => rp.PermissionId,
                    p => p.Id,
                    (rp, p) => p)
                .Where(p => p.MenuId.HasValue && p.Type == "menu" && p.Status == 1)
                .Join(_terraDbContext.Menus,
                    p => p.MenuId,
                    m => m.Id,
                    (p, m) => m)
                .Include(m => m.Permission)
                .Where(m => m.Status == 1) // 只获取启用的菜单
                .OrderBy(m => m.Sort)
                .Distinct()

                .ToListAsync();

            return menus;
        }

        public async Task<List<Permission>> GetByMenuIdAsync(Guid menuId)
        {
            return await _dbSet
                .Where(p => p.MenuId == menuId)
                .ToListAsync();
        }

        public async Task<Permission> GetByCodeAsync(string code)
        {
            return await _dbSet
                .FirstOrDefaultAsync(p => p.Code == code);
        }

        public async Task<List<Permission>> CreatePermissionsAsync(List<Permission> permissions)
        {
            await _dbSet.AddRangeAsync(permissions);
            await _terraDbContext.SaveChangesAsync();
            return permissions;
        }

        public async Task<bool> DeleteByMenuIdAsync(Guid menuId)
        {
            var permissions = await _dbSet
                .Where(p => p.MenuId == menuId && !p.IsSystem)
                .ToListAsync();

            if (!permissions.Any())
                return true;

            _dbSet.RemoveRange(permissions);
            return await _terraDbContext.SaveChangesAsync() > 0;
        }

        public async Task<bool> IsPermissionInUseAsync(Guid permissionId)
        {
            return await _terraDbContext.Set<RolePermission>()
                .AnyAsync(rp => rp.PermissionId == permissionId);
        }

        public async Task<List<Permission>> UpdatePermissionsAsync(List<Permission> permissions)
        {
            _dbSet.UpdateRange(permissions);
            await _terraDbContext.SaveChangesAsync();
            return permissions;
        }
    }
}
